# Algorithm Visualizer

## Introduction

This is a [Löve](https://love2d.org/) program that allows you to use the Löve framework, but instead of using event callbacks, you poll the events via function calls.

It requires a love2d version from 0.9 up.

It was inspired by forum member Neku, who was used to PyGame and had trouble with event-oriented programming when applied to the visualization of the algorithms he wrote for solving certain tasks.

And that's indeed the main application of this library: algorithm visualization. Even if you're deep in nested loops or recursion levels, calling `sleep()` will update your display thanks to the magic of coroutines.

A lot of inspiration for this version also came from the [TimelineEvents](https://love2d.org/forums/viewtopic.php?f=5&t=87592) library by Babulous, regarding the design and implementation of the whole event set instead of just a very limited set of functions and events.

## Usage

Just place your code in the file `mycode.lua`. Alternatively, you can call love2d with the name of the Lua file to run; for example, invoking `love . 8queens.lua` from the directory where this repository is, will execute `8queens.lua`.

A window is NOT automatically created; your code needs to call `love.graphics.setMode` first before calling any window functions.

Most Löve functions can be called directly. Note that there's an underlying canvas used as the framebuffer in which your graphics are rendered, therefore using `love.graphics.setCanvas()` may result in unintended consequences. This framebuffer canvas is available via a global variable called `fbcanvas`.

**NOTE:** Functions `love.graphics.setMode` and `love.event.pump` have been patched to work properly with this canvas, but other functions may not work as intended; let me know in case of problems so I can add a workaround.

**NOTE:** Redefining love2d events can have unintended consequences.

### API

In addition to Löve functions, there are several additional global functions:

- `sleep(t)`: Stops execution of your script during the given amount of time. Any events that happened during the sleep period are lost.
- `pause(t)`: Similar to `sleep`, but if the user presses any key or a mouse button, it will return before the time expires, and if the user presses ESC, the program will be immediately closed.
- `wait.<eventname>()`: This is actually a table with functions. For each Löve event, there is a corresponding function in this table. The function will stop execution of your script until the corresponding event is triggered, and then it will return whatever the arguments were for that event. These functions don't take any arguments.
  - For example, `wait.keypressed()` will wait until the `keypressed` event is triggered, and will return the `key`, `scancode` and `isRepeat` values that are the arguments of [love.keypressed](https://love2d.org/wiki/love.keypressed).
- `peek`: Another table with functions. Similar to `wait` but this one will return nothing instead of blocking your script, and will return the boolean `true` followed by the event's arguments if the current event is that one. Note, however, that calling a `peek` function will not advance to the next event; you need to call a function that does so yourself. For example, if you call `peek.` inside a loop without calling an event advancing function such as `poll()` or `wait.<something>()`, and your loop depends on some event in order to be interrupted, your program will hang indefinitely.
- In addition to the functions with the same name as the Löve events, the tables `wait` and `peek` contain another function called `event`. You can pass the name of an event to this function, and it will do the same as the function with the name of that event. Internally, every other function in the table calls this function. For example, `wait.keypressed()` and `wait.event("keypressed")` do the same. Note that the functions `wait.event()` and `peek.event()` should not be confused with the global function `event()`.
- `poll()` advances to the next event.
- `event()` is like `poll()` but it also returns the event name and its parameters. For example, if the next event to trigger is `keypressed`, and you call `event()`, it will return a tuple of the form `"keypressed", key, scancode, isRepeat`.
- `timer(seconds)` allows you to set a timer that will expire after the given number of seconds have passed (with 1 frame granularity) and generate the `timer` event.
- `quit()` immediately quits the program. It's a shortcut for `love.event.quit(); wait.quit(); poll()`.

In addition to the normal Löve events, there are three more events:

- `newframe` - Triggered at the start of a new frame. No parameters.
- `timer` - Triggered when `timer()` expires. No parameters.
- `sleep` - Generated internally by the `sleep()` call.

### Advanced usage

The functions that advance events all accept return parameters for the current event. The actual signatures are:

- `void sleep(t, ...)` \[\*\]
- `void pause(t, ...)` \[\*\]
- `void poll(...)`
- `tuple event(...)`
- `void wait.<eventname>(...)` \[\*\]
- `void wait.event(eventname, ...)` \[\*\]

The functions marked with \[\*\] may skip more than one event. In that case, the return value only applies to the first event.

Note that as of this writing, only the `quit` event handles a return value.

The `draw` event is called *after* drawing the framebuffer, but before the frame is displayed. This allows you to draw to the screen directly rather to the framebuffer, as long as you unset the canvas first with `love.graphics.setCanvas()`. Remember to restore the framebuffer if necessary by calling `love.graphics.setCanvas(fbcanvas)`.

Here's one example of the use of the `draw` event:

```lua
love.window.setMode(800, 600)
timer(3)
love.graphics.print("** Background", 0, 8) -- drawn to the framebuffer
repeat
  poll()
  if peek.draw() then
    -- We're in the draw event
    love.graphics.setCanvas() -- Unset the canvas
    -- This text overlaps the background temporarily:
    love.graphics.print("I appear for 3 seconds", 30, 0)
    love.graphics.setCanvas(fbcanvas) -- Restore the framebuffer
  end
until peek.timer() -- keep looping until the timer expires
love.graphics.print("Done", 0, 40)  -- drawn to the framebuffer again
pause()
quit()
```


## Examples

Simple example:

```lua
print("We're at the top level")
wait.load()  -- Wait for love.load() to trigger
print("Now we're inside love.load")
local dt = wait.update()  -- Wait for love.update() to trigger
print("Now we're inside love.update(), dt is " .. dt)
love.event.quit()  -- Send quit event
wait.quit()  -- Wait for love.quit() to trigger
print("Now we're inside love.quit(), but we don't want to quit")
poll(true)  -- Return true to love.quit, thus blocking the quit
print("See? We're still here");
love.event.quit()  -- Send quit event again
wait.quit()  -- Wait for love.quit() once more
print("Now we're inside love.quit() again, but this time we're quitting")
poll()  -- Return nothing to love.quit; this allows it to really quit
print("You can't see this!")  -- Program has terminated; this isn't reached
```

The example file `8queens.lua` is a program to solve the Eight Queens problem by brute force, with visualization of the intermediate positions and solutions found, using eight nested loops for demonstration purposes. An event-oriented version of this program would need to progress in small increments, making it less trivial to make than this straightforward version.

The example file `Nqueens.lua` is similar, but it implements a simple input function (with no cursor movement) to specify the number of queens, then solves the problem for any given number of queens from 4 to 16 instead of being fixed to 8. This variant is recursive and does N nested recursive calls.

Every file in this repository, including the images, is donated to the public domain or, if your jurisdiction does not contemplate donating things to the public domain, you have my permission to do anything you want with the files to the maximum extent permitted by law.
